﻿using SmarterCharger.App.Infrastructure;
using SmarterCharger.Library.Infrastructure.Interfaces;
using SmarterCharger.Library.Model;
using SmarterCharger.Library.Services.Interfaces;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;

namespace SmarterCharger.App.ViewModel
{
    public class EditSettingsViewModel : ViewModelBase
    {
        private const double DefaultChargeLimit = 80;
        private const double MaximumChargeLimit = 100;
        private const double MinimumChargeLimit = 1;
        private const double ChargeLimitStep = 1;

        private readonly ISettingsService _settingsService;
        private readonly ISmartPlugLoader _smartPlugLoader;

        #region Properties

        public ObservableCollection<SmartPlug> SmartPlugs { get; set; }

        private SmartPlug _selectedSmartPlug;
        public SmartPlug SelectedSmartPlug
        {
            get { return _selectedSmartPlug; }
            set
            {
                _selectedSmartPlug = value;
                RaisePropertyChanged("SelectedSmartPlug");
            }
        }

        private bool _isLoading;
        public bool IsLoading
        {
            get { return _isLoading; }
            internal set
            {
                _isLoading = value;
                RaisePropertyChanged("IsLoading");
                (AddChargeLimitCommand as DelegateCommand).RaiseCanExecuteChanged();
                (SubtractChargeLimitCommand as DelegateCommand).RaiseCanExecuteChanged();
            }
        }

        private double _chargeLimit;
        public double ChargeLimit
        {
            get { return _chargeLimit; }
            set
            {
                _chargeLimit = value;
                RaisePropertyChanged("ChargeLimit");
                (AddChargeLimitCommand as DelegateCommand).RaiseCanExecuteChanged();
                (SubtractChargeLimitCommand as DelegateCommand).RaiseCanExecuteChanged();
            }
        }

        #endregion

        public EditSettingsViewModel(ISettingsService settingsService, ISmartPlugLoader smartPlugLoader)
        {
            if (settingsService == null) throw new ArgumentNullException("settingsService");
            if (smartPlugLoader == null) throw new ArgumentNullException("smartPlugLoader");

            _settingsService = settingsService;
            _smartPlugLoader = smartPlugLoader;

            SmartPlugs = new ObservableCollection<SmartPlug>();
            AddChargeLimitCommand = new DelegateCommand(AddChargeLimit, CanAddChargeLimit);
            SubtractChargeLimitCommand = new DelegateCommand(SubtractChargeLimit, CanSubtractChargeLimit);
        }

        #region Commands

        public ICommand AddChargeLimitCommand { get; set; }
        public ICommand SubtractChargeLimitCommand { get; set; }

        private void SubtractChargeLimit(object obj)
        {
            ChargeLimit -= ChargeLimitStep;
        }

        private void AddChargeLimit(object obj)
        {
            ChargeLimit += ChargeLimitStep;
        }

        private bool CanAddChargeLimit(object arg)
        {
            return !IsLoading
                && (ChargeLimit + ChargeLimitStep <= MaximumChargeLimit);
        }

        private bool CanSubtractChargeLimit(object arg)
        {
            return !IsLoading
                && (ChargeLimit - ChargeLimitStep >= MinimumChargeLimit);
        }

        #endregion

        public void LoadData()
        {
            if (IsLoaded)
                return;

            SelectedSmartPlug = _settingsService.GetDefaultSmartPlug();
            GetSmartPlugs();
            ChargeLimit = _settingsService.GetChargeLimit() ?? DefaultChargeLimit;

            IsLoaded = true;
        }

        private async void GetSmartPlugs()
        {
            IsLoading = true;

            var selectedSmartPlug = SelectedSmartPlug;
            SelectedSmartPlug = null;
            SmartPlugs.Clear();

            var username = _settingsService.GetUsername();
            var password = _settingsService.GetPassword();
            var result = await _smartPlugLoader.Load(username, password);

            result.SmartPlugs.ToList().ForEach(s => SmartPlugs.Add(s));

            if (selectedSmartPlug != null)
                if (SmartPlugs.Any(s => s.EnergyDeviceId == selectedSmartPlug.EnergyDeviceId))
                    SelectedSmartPlug = SmartPlugs.Single(s => s.EnergyDeviceId == selectedSmartPlug.EnergyDeviceId);

            IsLoading = false;
        }

        public void SaveData()
        {
            if(SelectedSmartPlug != null)
                _settingsService.UpdateDefaultSmartPlug(SelectedSmartPlug);

            _settingsService.UpdateChargeLimit(ChargeLimit);
        }
    }
}
